<template>
  <div class="chat-wrapper">
    <Chat
      :participants="participants"
      :onMessageWasSent="onMessageWasSent"
      :messageList="messageList"
      :newMessagesCount="newMessagesCount"
      :isOpen="isChatOpen"
      :close="closeChat"
      :open="openChat"
      :showEmoji="false"
      :showFile="false"
      :showEdition="true"
      :showDeletion="true"
      :showTypingIndicator="showTypingIndicator"
      :showLauncher="true"
      :showCloseButton="true"
      :colors="colors"
      :alwaysScrollToBottom="alwaysScrollToBottom"
      :disableUserListToggle="false"
      :messageStyling="messageStyling"
      :draggle="true"
      :dynamicHeight="true"
      placeholder="请输入"
    >
      <!-- 自定义头部 -->
      <template v-slot:header>
        <div class="header">
          <div class="clock">
            <img class="clock-icon" :src="clockIcon" alt="" />
            <span>{{ showExamTime }}</span>
          </div>
          <el-popconfirm title="确定要结束答题吗？" @confirm="onEnd">
            <el-button class="custom-gray-btn" slot="reference"
              >结束答题</el-button
            >
          </el-popconfirm>
        </div>
      </template>

      <!-- 自定义text对话框 -->
      <template v-slot:text-message-body="{ message, messageText }">
        <div class="card" v-if="message.customType === 'card'">
          <img :src="nodeIcon" alt="" class="card-icon" />
          实操节点
          <div class="outside-bottom">
            <span
              class="red-text"
              :class="{ 'green-text': isPass(message.data) }"
              >{{ message.data.score }}分</span
            >
            <span>/{{ message.data.totalScore }}分</span>
          </div>
        </div>
        <div v-else class="custom-message-body">
          {{ messageText }}
          <Speaker
            class="custom-speaker"
            :isPlaying="message.data.isPlaying"
            @onClick="playAudio(message.index)"
          />
          <audio :ref="`audio${message.index}`" @ended="audioEnded(message)">
            <source :src="message.data.audio" type="audio/mpeg" />
            您的浏览器不支持 audio 标签。
          </audio>
          <div v-if="showHelp(message)" class="help" @click="toggleHelp">
            帮助引导
          </div>
        </div>
      </template>

      <!-- 自定义输入 -->
      <template v-slot:user-input>
        <div v-if="step !== 'finish'" class="answer-wrapper-col">
          <el-button
            class="btn"
            :type="INPUT_CONTENT_STEP[step].btnType"
            :disabled="btnDisabled"
            @click="handleInputBtn"
            >{{ INPUT_CONTENT_STEP[step].btnText }}</el-button
          >
          <div class="desc">
            {{ INPUT_CONTENT_STEP[step].desc }}
          </div>
          <div v-if="step === 'working'" class="action-desc">
            <img :src="bookIcon" alt="" class="action-desc-icon" />
            <span class="action-desc-text">{{
              INPUT_CONTENT_STEP[step].actionDesc
            }}</span>
          </div>
        </div>
        <div v-else class="answer-wrapper-row">
          <el-popconfirm
            title="确定要重新答题吗？"
            class="custom-pop-confirm"
            @confirm="onReset"
          >
            <el-button slot="reference" class="btn">重新答题</el-button>
          </el-popconfirm>
          <el-button
            type="primary"
            class="btn"
            :disabled="btnDisabled"
            @click="onFinish"
            >完成</el-button
          >
        </div>
      </template>
    </Chat>
  </div>
</template>

<script>
import Chat from "@/components/chat";
import nodeIcon from "@/assets/images/chat/node.png";
import bookIcon from "@/assets/images/chat/book.png";
import clockIcon from "@/assets/images/chat/clock.png";
import userImage from "@/assets/images/chat/user.png";
import examinerImage from "@/assets/images/chat/examiner.png";
import { queryTaskByMore, selectAudio, deleteFlow } from "@/api";
import Speaker from "@/components/speaker";
import moment from "moment";

const INPUT_CONTENT_STEP = {
  start: {
    desc: "注意事项：准备完毕，请点击按钮，根据内容操作系统界面",
    btnText: "开始答题",
    btnType: "primary",
  },
  working: {
    actionDesc: "操作记录中...",
    btnText: "完成答题",
    btnType: "success",
  },
};

const NODE_TYPE_MAP = {
  start: "1",
  question: "2",
  ending: "3",
};

export default {
  name: "ChatComponent",
  components: {
    Chat,
    Speaker,
  },
  data() {
    return {
      nodeIcon,
      clockIcon,
      bookIcon,
      INPUT_CONTENT_STEP,
      btnDisabled: false,
      step: "start",
      participants: [
        {
          id: "examiner",
          name: "examiner",
          imageUrl: examinerImage,
        },
        {
          id: "me",
          name: "me",
          imageUrl: userImage,
        },
      ],
      messageList: [],
      newMessagesCount: 0,
      isChatOpen: true,
      showTypingIndicator: "",
      colors: {
        header: {
          bg: "#fff",
          text: "#666",
        },
        launcher: {
          bg: "#268FFFE5",
        },
        messageList: {
          bg: "#ffffff",
        },
        sentMessage: {
          bg: "#349AF8",
          text: "#FFFCFB",
        },
        receivedMessage: {
          bg: "#E3ECFF",
          text: "#1D2129",
        },
        userInput: {
          bg: "#f4f7f9",
          text: "#565867",
        },
      },
      alwaysScrollToBottom: false,
      messageStyling: true,
      questionOrder: "", // 问题顺序
      index: -1,
      examTime: moment("00:00:00", "HH:mm:ss"),
      startTime: "",
      timer: null,
    };
  },
  computed: {
    showExamTime() {
      return moment(this.examTime).format("HH:mm:ss");
    },
  },
  methods: {
    showHelp(message) {
      const examType = JSON.parse(localStorage.getItem("examType"));
      const isQuestion =
        message.data.allInfo?.nodeType === NODE_TYPE_MAP.question;
      return examType === "2" && isQuestion;
    },
    isPass(data) {
      return data.score / data.totalScore >= 0.6;
    },
    handleInputBtn() {
      this.btnDisabled = true;

      if (this.step === "start") {
        this.onStart();
        this.step = "working";
      } else if (this.step === "working") {
        this.beforeFinish();
        this.step = "finish";
      }
    },

    async onStart() {
      await this.getMessage();

      this.startClock();
      this.btnDisabled = false;
      this.startTime = moment().format("YYYY-MM-DD HH:mm:ss");

      this.autoPlayAudio();
    },
    // 开始计时
    startClock() {
      this.timer = setInterval(this.addExamTime, 1000);
    },
    endClock() {
      clearInterval(this.timer);
    },
    addExamTime() {
      this.examTime = moment(this.examTime).add(1, "s");
    },
    beforeFinish() {
      this.$emit("onSubmit", {
        startTime: this.startTime,
        endTime: moment().format("YYYY-MM-DD HH:mm:ss"),
      });
    },
    async onFinish() {
      this.btnDisabled = true;
      await this.getMessage();

      this.autoPlayAudio(this.index);
      const latestNodeType =
        this.messageList[this.messageList.length - 1]?.data.allInfo.nodeType;

      if (latestNodeType === NODE_TYPE_MAP.question) {
        this.btnDisabled = false;
        this.step = "working";
      }
    },
    onEnd() {
      this.$emit("onEnd", {
        startTime: this.startTime,
        endTime: moment().format("YYYY-MM-DD HH:mm:ss"),
      });
      this.endClock();
    },
    async getMessage() {
      try {
        const [res, audioUrl] = await Promise.all([
          this.fetchTaskData(),
          this.fetchAudioUrl(),
        ]);

        this.updateIndexAndQuestionOrder(res);

        this.createMessage(res, audioUrl);

        const bdCourseId = res.bdCourseId;
        if (bdCourseId) {
          this.$emit("onChangeCourse", bdCourseId);
        }
      } catch (error) {
        console.log("error", error);
      }
    },
    async fetchTaskData() {
      const postData = {
        uuid: this.$store.state.user.userId,
        questionOrder: this.questionOrder,
      };
      return await queryTaskByMore(postData);
    },
    async fetchAudioUrl() {
      const postData = {
        uuid: this.$store.state.user.userId,
        questionOrder: this.questionOrder || "1",
      };
      const audioRes = await selectAudio(postData);
      return process.env.VUE_APP_ASSETS_URL + audioRes.audioUrl;
    },
    updateIndexAndQuestionOrder(res) {
      ++this.index;
      this.questionOrder = res.questionOrder + 1;
    },
    createMessage(res, audioUrl) {
      const currentIndex = this.index;
      const message = {
        index: currentIndex,
        type: "text",
        author: "examiner",
        data: {
          text: res.nodeContent,
          allInfo: res,
          audio: audioUrl,
        },
      };
      this.messageList.push(message);
    },
    autoPlayAudio(startIndex = 0) {
      if (this.index === -1 || startIndex < 0) return;

      const playNextAudio = (index) => {
        if (index <= this.index) {
          this.playAudio(index);
          const audioElement = this.$refs[`audio${index}`];

          // 音频播放结束时触发播放下一个音频
          const eventListener = () => {
            playNextAudio(index + 1);
            audioElement.removeEventListener("ended", eventListener);

            // 如果播放了结束语音，则进入答题结果页
            if (
              this.messageList[index].data.allInfo.nodeType ===
              NODE_TYPE_MAP.ending
            ) {
              this.endClock();
              this.$router.push("/exam-result");
            }
          };
          audioElement?.addEventListener("ended", eventListener);
        }
      };

      playNextAudio(startIndex);
    },
    playAudio(index) {
      const audioElement = this.$refs[`audio${index}`];

      if (!audioElement) return;

      const message = this.messageList[index];
      const audioSource = message.data.audio;
      audioElement.src = audioSource;
      audioElement.load(); // 手动加载音频数据

      audioElement.addEventListener("canplaythrough", () => {
        // 音频已准备好，可以播放
        audioElement.play(); // 播放音频
        const newMessageStatus = this.messageList[index];
        newMessageStatus.data.isPlaying = true;
        this.$set(this.messageList, index, newMessageStatus);
      });
    },
    audioEnded(message) {
      const index = message.index;
      message.data.isPlaying = false;
      this.$set(this.messageList, index, message);
    },
    async onReset() {
      const latestIndex = this.messageList.length - 1;
      const latestMessage = this.messageList[latestIndex]?.data;
      await deleteFlow({ rollbackId: latestMessage.rollbackId });

      this.$emit("onReset", latestMessage.bdCourseId);
      this.messageList.splice(latestIndex, 1);
      this.index--;
      this.step = "working";
    },
    toggleHelp() {
      this.$emit("toggleHelp", true);
    },

    onMessageWasSent(message) {
      this.messageList = [...this.messageList, message];
    },
    openChat() {
      this.isChatOpen = true;
      this.newMessagesCount = 0;
    },
    closeChat() {
      this.isChatOpen = false;
    },
  },
  async created() {
    this.btnDisabled = true;
    await this.getMessage();
    this.btnDisabled = false;
  },
};
</script>

<style lang="scss" scoped>
.chat-wrapper {
  position: relative;
  z-index: 999;

  .header {
    flex: 1;
    display: flex;
    position: relative;
    width: 100%;
    text-align: center;

    .clock {
      flex: 1;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #666;
      font-size: 14px;
      font-weight: 400;

      &-icon {
        width: 20px;
        object-fit: contain;
        margin-right: 10px;
      }
    }

    .custom-gray-btn {
      background: #f2f3f5;
      color: #4e5969;
      border: none;
    }
  }

  .answer-wrapper {
    display: flex;
    width: 100%;
    height: 92px;
    padding: 20px 24px;
  }

  .answer-wrapper-col {
    @extend .answer-wrapper;
    position: relative;
    flex-direction: column;

    .desc {
      color: #f53f3f;
      font-size: 12px;
      font-weight: 400;
      line-height: 22px;
      margin-top: 15px;
      text-align: center;
    }

    .btn {
      width: 100%;
    }

    .action-desc {
      position: absolute;
      top: -50px;
      right: 6px;
      height: 40px;
      line-height: 40px;
      border-radius: 50px;
      background: #fff;
      box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.25);
      padding: 0 16px;

      &-icon {
        width: 17px;
        object-fit: contain;
        vertical-align: middle;
        margin-right: 4px;
      }

      &-text {
        color: #666;
        font-size: 14px;
        font-weight: 400;
        vertical-align: middle;
      }
    }
  }

  .answer-wrapper-row {
    @extend .answer-wrapper;
    align-items: center;

    .custom-pop-confirm {
      width: 100%;
      margin-right: 12px;
    }

    .btn {
      width: 100%;
    }
  }

  .card {
    position: relative;
    height: 68px;
    line-height: 68px;
    font-size: 24px;
    font-weight: 400;
    padding: 0 12px;

    &-icon {
      width: 38px;
      height: 38px;
      object-fit: contain;
      vertical-align: middle;
      margin-right: 8px;
    }

    .outside-bottom {
      position: absolute;
      bottom: -28px;
      left: -10px;
      color: #666;
      font-size: 12px;
      font-weight: 400;
      line-height: 20px;

      .red-text {
        color: #f53f3f;

        &.green-text {
          color: #00b42a;
        }
      }
    }
  }
}

.custom-message-body {
  position: relative;

  .custom-speaker {
    position: absolute;
    right: -90px;
    top: -15px;
  }

  .help {
    position: absolute;
    left: -10px;
    bottom: -35px;
    border-radius: 2px;
    background: #e8f3ff;
    color: #4080ff;
    font-size: 12px;
    font-weight: 400;
    line-height: 20px;
    padding: 0 10px;
    cursor: pointer;
  }
}
</style>
